#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the version 3 of the GNU Lesser General Public License
#   as published by the Free Software Foundation.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Copyright (c) NEC Deutschland GmbH, NEC HPC Europe
#
# $Id$

import os

from aggmon.databases.metric.time_series_database import TimeSeriesDatabase, S_IN_DAY, NS_IN_S
from aggmon.databases.metric.rry import RRY
from basic_types import NumRecord


__all__ = ["RRA"]


# Constants
S_IN_WEEK = 7 * S_IN_DAY
WIDTH_RRA = 10000
#for test only
#WIDTH_RRA = 70


class RRA(TimeSeriesDatabase):
    """
    A RRA (Round Robin Archive) contains condensed numeric-typed metrics.
    """

    def __init__( self, dir_path, keep_exact=-1, rotation_period=S_IN_WEEK, width=WIDTH_RRA, *args ):
        super( RRA, self ).__init__( dir_path, keep_exact=keep_exact, rotation_period=rotation_period, *args )
        self.__width = width

    def append( self, time_ns, value ):
        assert False, "Usage error. Append is not possible!"

    def cascade( self, int_file_list ):
        """
        Condense files.
        """
        import logging
        file_path = os.path.dirname( int_file_list[0] )
        for file_name in int_file_list:
            rry = RRY( file_path, keep_exact=self._keep_exact )
            rotation_period_rra = self.get_rotation_period()
            rotation_period_rry = rry.get_rotation_period()
            step_ns = rotation_period_rra / int( rotation_period_rra / int ( rotation_period_rry / rry.getWidth() ) ) * NS_IN_S
            records = super( RRA, self ).fetch_all( selected_files=[file_name] )
            logging.debug( "RRA.cascade(): %d records read from %s" % (len( records ), file_name) )
            #self._dump_records( records )
            records = super( RRA, self ).fetch_all( step_ns=step_ns , selected_files=[file_name] )
            logging.debug( "RRA.cascade(): num of condensed records %d" % len( records ) )
            #self._dump_records( records )
            for record in records:
                rry.insert( record.time_ns, record.value )
            # remove RRA file
            os.unlink( file_name )
            logging.debug( "RRA.cascade(): removed file " + file_name )

        if rry.number_of_files_to_condense() > 0:
            int_file_list = rry.get_files_to_condense()
            rry.cascade( int_file_list )

    def fetch_all( self, from_ns=0, to_ns=0, nsteps=0, step_ns=0, selected_files=None ):
        """
        This function overrides fetch_all in TimeSeriesDatabase and digs into
        condensed data files. If a file to read from is specified just read it and leave.
        """
        records = []
        if selected_files == None:
            rry = RRY( self._dir_path, keep_exact=self._keep_exact )
            records = rry.fetch_all( from_ns, to_ns, nsteps, step_ns )
        records.extend( super( RRA, self ).fetch_all( from_ns, to_ns, nsteps, step_ns, selected_files ) )
        return records

    def getWidth( self ):
        return self.__width

    def insert( self, time_ns, value ):
        self.insert_record( NumRecord( time_ns, value ) )

    def record( self ):
        return NumRecord()
    
    def _write_ts_info( self ):
        pass


from basic_types.factory import Factory
Factory.set_factory( "RRA", RRA, __name__ )
